﻿using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;

namespace SmartBot
{
    /// <summary>
    /// Chứa các hàm hỗ trợ cho auto
    /// </summary>
    public class Helper
    {
        /// <summary>
        /// Quy định mã trả về sau khi đăng nhập
        /// </summary>
        public enum LoginCode
        {
            LOGIN_OK = 1,
            LOGIN_USERNAME_PASSWORD_ERROR = -1,
            LOGIN_EXPIRES = -2,
        }
        /// <summary>
        /// 
        /// </summary>
        public class Converter
        {

        }

        /// <summary>
        /// Class hỗ trợ lấy ID của phần cứng (HWID)
        /// </summary>
        /// <return>ID của phần cứng, chuỗi 32 ký tự</return>
        public class HWID
        {
            public string Value
            {
                get
                {
                    return GetHash( "CPU >> " + CpuID() + "\nBASE >> " + BaseID() + "\nMAC >> " + MacID());
                }
            }

            /// <summary>
            /// Lấy chuỗi mã hóa dạng hex từ thông tin phần cứng
            /// </summary>
            /// <param name="strSource"></param>
            /// <returns></returns>
            private static string GetHash(string strSource)
            {
                MD5 sec = new MD5CryptoServiceProvider();
                ASCIIEncoding enc = new ASCIIEncoding();
                byte[] bt = enc.GetBytes(strSource);
                return GetHexString(sec.ComputeHash(bt));
            }

            /// <summary>
            /// Function nay chức năng là gì vậy cha nội?
            /// </summary>
            /// <param name="bt"></param>
            /// <returns></returns>
            private static string GetHexString(byte[] bt)
            {
                string s = string.Empty;
                for (int i = 0; i < bt.Length; i++)
                {
                    byte b = bt[i];
                    int n, n1, n2;
                    n = (int)b;
                    n1 = n & 15;
                    n2 = (n >> 4) & 15;
                    if (n2 > 9)
                        s += ((char)(n2 - 10 + (int)'A')).ToString();
                    else
                        s += n2.ToString();
                    if (n1 > 9)
                        s += ((char)(n1 - 10 + (int)'A')).ToString();
                    else
                        s += n1.ToString();
                    if ((i + 1) != bt.Length && (i + 1) % 2 == 0) s += "-";
                }
                return s;
            }

            #region Original Device ID Getting Code
            
            /// <summary>
            /// Return a hardware identifier
            /// </summary>
            /// <param name="wmiClass"></param>
            /// <param name="wmiProperty"></param>
            /// <param name="wmiMustBeTrue"></param>
            /// <returns></returns>
            private static string Identifier(string wmiClass, string wmiProperty, string wmiMustBeTrue)
            {
                string result = "";
                System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
                System.Management.ManagementObjectCollection moc = mc.GetInstances();
                foreach (System.Management.ManagementObject mo in moc)
                {
                    if (mo[wmiMustBeTrue].ToString() == "True")
                    {
                        //Only get the first one
                        if (result == "")
                        {
                            try
                            {
                                result = mo[wmiProperty].ToString();
                                break;
                            }
                            catch
                            {
                            }
                        }
                    }
                }
                return result;
            }
            
            /// <summary>
            /// Return a hardware identifier
            /// </summary>
            /// <param name="wmiClass"></param>
            /// <param name="wmiProperty"></param>
            /// <returns></returns>
            private static string Identifier(string wmiClass, string wmiProperty)
            {
                string result = "";
                System.Management.ManagementClass mc = new System.Management.ManagementClass(wmiClass);
                System.Management.ManagementObjectCollection moc = mc.GetInstances();
                foreach (System.Management.ManagementObject mo in moc)
                {
                    //Only get the first one
                    if (result == "")
                    {
                        try
                        {
                            result = mo[wmiProperty].ToString();
                            break;
                        }
                        catch
                        {
                        }
                    }
                }
                return result;
            }

            /// <summary>
            /// Return CPU ID
            /// </summary>
            /// <returns></returns>
            private static string CpuID()
            {
                //Uses first CPU identifier available in order of preference
                //Don't get all identifiers, as very time consuming
                string retVal = Identifier("Win32_Processor", "UniqueId");
                if (retVal == "") //If no UniqueID, use ProcessorID
                {
                    retVal = Identifier("Win32_Processor", "ProcessorId");
                    if (retVal == "") //If no ProcessorId, use Name
                    {
                        retVal = Identifier("Win32_Processor", "Name");
                        if (retVal == "") //If no Name, use Manufacturer
                        {
                            retVal = Identifier("Win32_Processor", "Manufacturer");
                        }
                        //Add clock speed for extra security
                        retVal += Identifier("Win32_Processor", "MaxClockSpeed");
                    }
                }
                return retVal;
            }

            /// <summary>
            /// BIOS Identifier
            /// </summary>
            /// <returns></returns>
            private static string BiosID()
            {
                return Identifier("Win32_BIOS", "Manufacturer")
                + Identifier("Win32_BIOS", "SMBIOSBIOSVersion")
                + Identifier("Win32_BIOS", "IdentificationCode")
                + Identifier("Win32_BIOS", "SerialNumber")
                + Identifier("Win32_BIOS", "ReleaseDate")
                + Identifier("Win32_BIOS", "Version");
            }
            
            /// <summary>
            /// Main physical hard drive ID
            /// </summary>
            /// <returns></returns>
            private static string DiskID()
            {
                return Identifier("Win32_DiskDrive", "Model")
                + Identifier("Win32_DiskDrive", "Manufacturer")
                + Identifier("Win32_DiskDrive", "Signature")
                + Identifier("Win32_DiskDrive", "TotalHeads");
            }
            //Motherboard ID
            private static string BaseID()
            {
                return Identifier("Win32_BaseBoard", "Model")
                + Identifier("Win32_BaseBoard", "Manufacturer")
                + Identifier("Win32_BaseBoard", "Name")
                + Identifier("Win32_BaseBoard", "SerialNumber");
            }
            //Primary video controller ID
            private static string VideoID()
            {
                return Identifier("Win32_VideoController", "DriverVersion")
                + Identifier("Win32_VideoController", "Name");
            }
            //First enabled network card ID
            private static string MacID()
            {
                return Identifier("Win32_NetworkAdapterConfiguration", "MACAddress", "IPEnabled");
            }
            #endregion
        }

        /// <summary>
        /// Log to file the message - this is for technical support.
        /// </summary>
        /// <param name="msg"></param>
        /// <param name="options"></param>
        public static void LogToFile(string msg, params object[] options)
        {
            StreamWriter logFile = null;

            //Rotate log file
            if (File.Exists(frmLogin.MainClass.GlobalSetting.LogFilePath))
            {
                //Check size of the file and if it's over 5 MB --> rotate
                FileInfo info = new FileInfo(frmLogin.MainClass.GlobalSetting.LogFilePath);
                if (info != null)
                {
                    if (info.Length >= frmLogin.MainClass.GlobalSetting.LogFileMaxSize * 1000000)
                    {
                        //Rename the current file to support.log. -> hhmmss_mmddyyyy.log
                        string newPath = AppDomain.CurrentDomain.BaseDirectory +
                            string.Format("log\\{0:D2}{1:D2}{2:D2}_{3:D2}{4:D2}{5:D4}.log", DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second,
                            DateTime.Now.Month, DateTime.Now.Day, DateTime.Now.Year);

                        try
                        {
                            File.Move(frmLogin.MainClass.GlobalSetting.LogFilePath, newPath);
                        }
                        finally
                        {
                            info = null;
                            GC.Collect();
                        }
                    }
                }
            }

            try
            {
                msg = string.Format(msg, options);
                string logLine = string.Format("{0}: {1}", DateTime.Now.ToString(), msg);

                lock (frmMain.frmMainInstance.GUILocker)
                {
                    logFile = new StreamWriter(frmLogin.MainClass.GlobalSetting.LogFilePath, true);
                    if (logFile != null)
                    {
                        logFile.WriteLine(logLine);
                    }
                }

            }
            catch (Exception ex)
            {
                Helper.Message("Không tìm thấy folder log trong thư mục gốc của auto.");
            }
            finally
            {
                //Close the log file anyway
                if (logFile != null)
                    logFile.Close();
            }
        }

        /// <summary>
        /// Tạo name pipe ngẫu nhiên để pass sang Dll. Chiều dài của file name là 24 kí tự để tránh bị tờ rùng.
        /// </summary>
        /// <returns></returns>
        public static string GenerateRandomName()
        {
            var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
            var stringChars = new char[24];
            var random = new Random();

            for (int i = 0; i < stringChars.Length; i++)
            {
                stringChars[i] = chars[random.Next(chars.Length)];
            }

            var finalString = new String(stringChars);
            return finalString;
        }

        

        /// <summary>
        /// Message box thay thế MessageBox của hệ thống
        /// </summary>
        /// <param name="strMessage"></param>
        public static void Message(string strMessage)
        {
            MessageBox.Show(strMessage, "SmartBot TLBB", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
}
